
// dispatch(type: string, payload?: any, options?: Object): Promise<any>

// dispatch(action: Object, options?: Object): Promise<any>

// 第一种形式是通过type和payload参数来触发action。type参数是action的类型，payload参数是传递给action的数据。
// options参数是一个可选的对象，用于指定一些额外的选项。
// 第二种形式是直接传递一个action对象来触发action。action对象包含type和payload属性，用于指定action的类型和数据。options参数同样是一个可选的对象。
// dispatch方法都会返回一个Promise对象，以便在action执行完成后进行后续操作
class vuex {
  dispatch(_type, _payload) {
    // 检测参数类型并进行相应调整
    const {
      type, // 触发的类型 ，例如：store.dispatch('increment')
      payload, // 提交的载荷即参数，例如：store.dispatch('increment', 10)
      // unifyObjectStyle 方法接受一个对象作为参数，并返回一个新的对象。如果传入的对象是一个数组，
      // 则返回一个新的数组，其中每个元素都是通过 unifyObjectStyle 方法转换后的对象。
    } = unifyObjectStyle(_type, _payload);

    // 用于从一个对象中提取属性并赋值给对应的变量。
    // unifyObjectStyle 函数接受 _type 和 _payload 作为参数，并返回一个对象。
    // 然后，通过解构赋值将返回的对象中的 type 属性赋值给变量 type，将 payload 属性赋值给变量 payload。

    // 根据注释的说明，这段代码可能是用于统一处理不同风格的参数传递方式。
    // 例如，可以通过 store.dispatch('increment') 或 store.dispatch('increment', 10) 的方式调用 dispatch 函数，
    // 并通过解构赋值将传递的参数提取出来，分别赋值给 type 和 payload 变量。

    const action = {
      type,
      payload,
    };
    // this._actions，store实例定义的用于存储action的对象

    // 它通过 this._actions[type] 的方式获取一个名为 entry 的变量。根据代码中的注释，
    // entry 可能是一个存储了不同类型的操作（action）的对象。
    const entry = this._actions[type];
    // entry不存在就阻止运行
    if (!entry) {
      // 进行了一个条件判断，检查 entry 是否存在。如果 entry 不存在，
      // 说明没有找到对应类型的操作（action），就会执行相应的逻辑。
      if (__DEV__) {
        // 在开发环境中（根据 __DEV__ 变量判断），会输出一条错误信息到控制台，
        // 提示未知的操作类型。并返回，阻止继续运行。
        console.error(`[vuex] unknown action type: ${type}`);
      }
      return;
    }
    // 38-49这块代码的作用就是  检查给定的操作类型是否存在于 _actions 对象中，
    // 如果不存在则输出错误信息并阻止继续执行。这可能是在一个 Vuex
    // 或类似的状态管理库中用于处理未知操作类型的情况。

    try {
      // 这里运用了一个 try-catch 语句块，是用于捕获可能出现的异常并进行处理
      // 首先获取一个数组为 this._actionSubscribers，用于存储调用store.subscribeAction时，传入的函数
      this._actionSubscribers
    // 使用slice进行浅复制，是为防止订阅者同步调用取消订阅而造成的迭代器失效。
     // filter将符合条件（包含before属性）的元素筛选出来，组成一个新数组，然后通过forEach遍历这些元素
      // 此数组中的元素并调用before（即回调函数）。这个筛选条件与store实例方法：subscribeAction
      // 有关（稍后会介绍它）。
        .slice()
        .filter((sub) => sub.before) 
        .forEach((sub) => sub.before(action, this.state));
    } catch (e) {//如果在执行过程中出现了异常，那么代码会跳转到 catch 块中进行处理
      if (__DEV__) {//在开发环境中（根据 __DEV__ 变量判断），代码会输出一条警告信息到控制台，并输出异常信息。
        // 最后，无论是否出现异常，代码都会继续执行。
        // 54-72行这段代码可能是在 Vuex 或类似的状态管理库中用于处理 action 执行前的一些操作，例如记录日志或做一些异步处理。
        console.warn(`[vuex] error in before action subscribers: `);
        console.error(e);
      }
    }

    // 使用Promise.all的原因：一个store.dispatch在不同模块中可以触发多个action函数。
    // 在这种情况下，只有当所有触发函数完成后，返回的Promise才会执行。

    // 先检查 entry 数组的长度是否大于 1，如果是，说明有多个操作（action）处理函数，需要使用 Promise.all 方法将它们全部执行，
    // 并返回一个 Promise 对象；如果不是，说明只有一个操作处理函数，直接调用它并将 payload 作为参数传入即可。
    // 如果 entry 数组中有多个操作处理函数，那么代码会使用 map() 方法将这些函数依次执行，
    // 并将它们的返回值封装成一个 Promise 对象。最后通过 Promise.all() 方法将所有 Promise 对象合并成一个新的 Promise 对象，并将其赋值给变量 result。
    const result =
      entry.length > 1
        ? Promise.all(entry.map((handler) => handler(payload)))
        : entry[0](payload);
        // 81-84行的作用是根据 entry 数组中操作处理函数的数量选择不同的执行方式。
        // 如果有多个操作处理函数，那么使用 Promise.all 方法将它们全部执行并返回一个 Promise 对象；
        // 如果只有一个操作处理函数，那么直接调用它并将 payload 作为参数传入即可

    return new Promise((resolve, reject) => {//构造函数  
      result.then(
        (res) => {
          try {
            // filter将符合条件（包含after属性）的元素筛选出来，组成一个新数组，然后遍历
            // 此数组中的元素并调用after。这个筛选条件与store实例方法：subscribeAction有关。
            this._actionSubscribers
              .filter((sub) => sub.after)
              .forEach((sub) => sub.after(action, this.state));
          } catch (e) {
            if (__DEV__) {
              console.warn(`[vuex] error in after action subscribers: `);
              console.error(e);
            }
          }
          resolve(res);
        },
        (error) => {
          try {
            // filter将符合条件（包含error属性）的元素筛选出来，组成一个新数组，然后遍历
            // 此数组中的元素并调用的是error。这个筛选条件与store实例方法：subscribeAction有关,在触发action后执行一些额外的操作
            this._actionSubscribers
              .filter((sub) => sub.error)
              .forEach((sub) => sub.error(action, this.state, error));
          } catch (e) {
            if (__DEV__) {
              console.warn(`[vuex] error in error action subscribers: `);// 警告消息
              console.error(e);
            }
          }
          reject(error);
          // 通过调用resolve(res)或reject(error)来解决或拒绝这个Promise。
        }
      );
    });
  }
}

